package com.syslog.aop;


import java.lang.reflect.Method;
import java.util.Date;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.staff.dao.StaffRepository;
import com.staff.entity.Staff;
import com.staff.service.IStaffService;
import com.syslog.entity.Syslog;
import com.syslog.service.ISyslogService;

@Aspect
@Component
public class LogAspect {
	
	@Autowired
	ISyslogService logService;
	@Autowired
	private IStaffService staffService;
	
	/**
	 * 日志记录
	 */
	//private static final Logger LOGGER = Logger.getLogger(SystemServiceLog.class);
	
	/**
	 * serivce层切点
	 */

	@Pointcut("execution(* com.*.web.*.save*(..))")
	public void webSaveAspect(){};
	
	@Pointcut("execution(* com.*.web.*.find*(..))")
	public void webFindAspect(){};
	
	@Pointcut("execution(* com.*.web.*.delete*(..))")
	public void webDeleteAspect(){};
	
	//授权切点
	@Pointcut("execution(* com.*.web.*.*Authorized(..))")
	public void webAuthorizedAspect(){};
	
	/**
     * doServiceLog:获取注解参数，记录日志. 
     * @param joinPoint 切入点参数
     */
    @AfterReturning(value="webSaveAspect()",argNames="args",returning="args") 
	public void doWebSaveLog(JoinPoint joinPoint,Object args) {
		
    	//System.out.println("joinPoint:"+joinPoint+",args:"+args);
    	//LOGGER.info("日志记录");
		try {
			//获取当前管理员信息
			Subject subject=SecurityUtils.getSubject();
			String staffNum=(String) subject.getPrincipal();
			System.out.println("staffNum:"+staffNum);
			
			Staff staff = staffService.findOne(staffNum);

			//获取方法名  
			String methodName = joinPoint.getSignature().getName();
			//获取操作内容
			String opContent = optionContent(joinPoint.getArgs(), methodName);
			// 数据库日志
			Syslog log = new Syslog();
			// 获取日志描述信息
			
			String description = getServiceMethodDescription(joinPoint);
			//记录到数据库
			if(description!=null&&!"".equals(description)){
				log.setStaffName(staff.getStaffName());
				log.setDescription("进行了#"+description+"#操作:"+ opContent);
				//log.setContent(user.getUserName() +"进行了#"+description+"#操作:"+ opContent);
				log.setTime(new Date());
				//System.out.println(opContent+"desc:"+description);
				logService.saveOrUpdate(log);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			//LOGGER.error("异常信息:{}", e);
		}
	}
    
    @AfterReturning(value="webFindAspect()",argNames="args",returning="args") 
   	public void doWebFindLog(JoinPoint joinPoint,Object args) {
    	this.doWebSaveLog(joinPoint, args);
    }
    
    @AfterReturning(value="webDeleteAspect()",argNames="args",returning="args") 
   	public void doWebDeleteLog(JoinPoint joinPoint,Object args) {
    	this.doWebSaveLog(joinPoint, args);
    }
    
    @AfterReturning(value="webAuthorizedAspect()",argNames="args",returning="args") 
   	public void doWebAuthorizedLog(JoinPoint joinPoint,Object args) {
    	this.doWebSaveLog(joinPoint, args);
    }
     
    /**
     * getServiceMthodDescription:获取注解中对方法的描述信息 用于service层注解 
     * @param joinPoint 切点 
     * @return 方法描述
     * @throws Exception 
     */
	private String getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class<?> targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				//@SuppressWarnings("rawtypes")
				boolean methodHasAnno = method.isAnnotationPresent(SystemServiceLog.class);
				if(methodHasAnno){
					Class[] clazzs = method.getParameterTypes();
					if (clazzs.length == arguments.length) {
						description = method.getAnnotation(SystemServiceLog.class).value();
						break;
					}
				}
			}
		}
		return description;
	}
    
    /**
	 * 获取方法的参数值，将参数值拼接为操作内容
	 * @param Object[] args, String mName
	 */
	public String optionContent(Object[] args, String mName) throws Exception{

		if (args == null) {
			return null;
		}
		
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		// 遍历参数对象
		for (Object info : args) {
			
			//获取对象类型
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			rs.append("[参数" + index + ",类型:" + className + ",返回值:");
			
			// 获取对象的所有方法
			Method[] methods = info.getClass().getDeclaredMethods();
			
			// 遍历方法，判断get方法
			for (Method method : methods) {
				
				String methodName = method.getName();
				// 判断是不是get方法
				if (methodName.indexOf("get") == -1) {// 不是get方法
					continue;// 不处理
				}
				//get集合方法不返回
				if("getPermissions".equals(methodName)||"getUsers".equals(methodName)){
					continue;
				}
				
				Object rsValue = null;
				try {
					
					// 调用get方法，获取返回值
					rsValue = method.invoke(info);
					
					if (rsValue == null) {//没有返回值
						continue;
					}
					
				} catch (Exception e) {
					continue;
				}
				
				//将值加入内容中
				rs.append("(" + methodName + " : " + rsValue + ")");
			}
			
			rs.append("]");
			
			index++;
		}
		
		return rs.toString();
	}


}
